#pragma once
#include "CXcpObjectBase.h"
#include "ICoreCompositorScheduler.h"
#include "CXcpObjectThreadSafeAddRefPolicy.h"

class CHardwareCompositor;
class UIThreadScheduler;
class RefreshAlignedClock;

class CompositorScheduler :
	public  CXcpObjectBase<ICoreCompositorScheduler,CXcpObjectThreadSafeAddRefPolicy>
{

private: 
	CompositorScheduler(struct IPALGraphicsDeviceManager * pIGraphicsDeviceManager);
	virtual ~CompositorScheduler();
public: 
	virtual XUINT32 AddRef();
	virtual XUINT32 Release();
	static HRESULT Create(struct IPALGraphicsDeviceManager * pIGraphicsDeviceManager, CompositorScheduler * * ppCompositorScheduler);
	virtual HRESULT WakeCompositionThread();
	virtual HRESULT Shutdown();
	virtual XBOOL IsShutdown();
	XBOOL IsStarted();
	HRESULT Startup();
	HRESULT RegisterCompositor(CHardwareCompositor * pHardwareCompositor);
	HRESULT UnregisterCompositor(CHardwareCompositor * pHardwareCompositor);
	void RegisterUIThreadScheduler(UIThreadScheduler * pScheduler, struct IPALTickableClock * * ppIClock);
	void UnregisterUIThreadScheduler(UIThreadScheduler * pScheduler);
	XBOOL IsIdle();
	XUINT32 GetRenderThreadId();
	struct IPALCriticalSection * GetDrawListsLock();
	virtual HRESULT GetRenderThreadHR();
	virtual void ClearRenderThreadHR();
	virtual HRESULT GetHRForSurfacePresenters();
	virtual void SetHRForSurfacePresenters(HRESULT hr);
	virtual enum RenderThreadState GetRenderThreadState();
	HRESULT ReleaseAllSwapChains();
	HRESULT RecreateAllSwapChains();
	void OnResourcesOffered();
	void OnResourcesReclaimed();
	virtual HRESULT ResumeRenderThreadAfterNewFrame();
	virtual HRESULT Suspend(CMetaCompositor * pCMetaCompositor, HWTextureManager * pHWTextureManager, struct ICoreServices * pCoreServices);
	virtual HRESULT Resume(HWTextureManager * pHWTextureManager);
	struct IPALGraphicsDeviceManager * GetGraphicsDeviceManager();
	void AddToBatchAndPrimitiveCounts(XUINT32 batchCount, XUINT32 primitiveCount);
	void OnNotifyWindowResize(XUINT32 applicationViewState);
	void EnableRender(XBOOL enable);
	virtual HRESULT OnRenderStateChanged(XBOOL isRenderEnabled);
private: 
	HRESULT Initialize();
	static XINT32 RenderThreadMainStatic(XUINT8 * pData);
	XINT32 RenderThreadMain();
	void RenderThreadFrame();
	XUINT32 EncounteredError();
	void SetRenderThreadState(enum RenderThreadState state);
	HRESULT EnsureRefreshRateInfo(CHardwareCompositor * pPrimaryCompositor, struct IPALDCompTreeHost * pDCompTreeHost);
	RefreshAlignedClock * m_pClock;
	struct IPALGraphicsDeviceManager * m_pIGraphicsDeviceManager;
	struct IPALWaitable * m_pRenderThread;
	volatile XBOOL m_fShutdownThread;
	struct IPALEvent * m_pCompositorWait;
	struct IPALCriticalSection * m_pUIThreadSchedulerLock;
	struct IPALCriticalSection * m_pRegisteredCompositorsLock;
	struct IPALCriticalSection * m_pDrawListsLock;
	UIThreadScheduler * m_pUIThreadSchedulerNoRef;
	xvector<CHardwareCompositor *> m_registeredCompositors;

private:
	struct IPALRefreshRateInfo * m_pRefreshRateInfo;
	XBOOL m_waitingForWork;
	XUINT32 m_renderThreadId;
	enum RenderThreadState m_renderThreadState;
	HRESULT m_renderThreadHR;
	HRESULT m_hrForSurfacePresenters;
	struct IPALCriticalSection * m_pSchedulerCommandLock;
	struct ISchedulerCommand * m_pPendingSchedulerCommand;
	XUINT32 m_batchCount;
	XUINT32 m_primitiveCount;
	struct ISchedulerCommand * m_pRenderStateChangedCommand;
	XBOOL m_windowResized;
	XBOOL m_isRenderEnabled;
	XBOOL m_wasSCBPOptimizationOn;
	XUINT32 m_windowViewStateOnResize;

};